home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / x+opengl / renderboth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.5 KB  |  400 lines

  1. /*
  2.  * Copyright 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  * renderboth
  20.  * 
  21.  * Demonstrates how to render both Open GL and X to the same window.  Based
  22.  * on Mark Kilgard's glxmotif example.
  23.  *
  24.  * Instructions: The arrow keys rotate the model manually.  The ESC key quits.
  25.  * 
  26.  * $Revision: 1.4 $
  27.  */
  28.  
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <Xm/Form.h>
  32. #include <Xm/Frame.h>
  33. #include <Xm/DrawingA.h>
  34. #include <X11/keysym.h>
  35. #include <X11/extensions/sgiXnmbx.h>
  36. #include <GL/gl.h>
  37. #include <GL/glu.h>
  38. #include <GL/glx.h>
  39.  
  40. static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None};
  41. static int doubleBuf[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, None};
  42.  
  43. static String   fallbackResources[] =
  44. {
  45.     "*glxarea*width: 300",
  46.     "*glxarea*height: 300",
  47.     "*frame*shadowType: SHADOW_IN",
  48.     NULL
  49. };
  50.  
  51. Display        *dpy;
  52. Bool            viewportUpdateNeeded = GL_TRUE;
  53. XtAppContext    app;
  54. Widget          toplevel, form, frame, glxarea;
  55. GC              gc;
  56.  
  57. void
  58. updateViewport(Widget w)
  59. {
  60.     Arg             args[2];
  61.     int             num;
  62.  
  63.     num = 0;
  64.     XtSetArg(args[num], XtNwidth, 0); num++;
  65.     XtSetArg(args[num], XtNheight, 0); num++;
  66.     XtGetValues(w, args, num);
  67.     glViewport(0, 0, (GLint) args[0].value - 1, (GLint) args[1].value - 1);
  68.     viewportUpdateNeeded = GL_FALSE;
  69. }
  70.  
  71.  
  72. static void
  73. makeGC (Colormap cmap)
  74. {
  75.    Display * display = XtDisplay(glxarea);
  76.    Window win = XtWindow(glxarea);
  77.    unsigned long     ply_mask;
  78.    Font font1  = XLoadFont (display,"9x15");
  79.    XGCValues         ply_vals;
  80.    XColor color_def;
  81.    Pixel black_pixel = 0, white_pixel = 0;
  82.  
  83.    XParseColor(display, cmap, "Black", &color_def);
  84.    XAllocColor(display, cmap, &color_def);
  85.    black_pixel = color_def.pixel;
  86.    XParseColor(display, cmap, "White", &color_def);
  87.    XAllocColor(display, cmap, &color_def);
  88.    white_pixel = color_def.pixel;
  89.  
  90.    ply_vals.function = GXcopy;
  91.    ply_vals.foreground = white_pixel;
  92.    ply_vals.background = black_pixel;
  93.    ply_vals.line_width = 5;
  94.    ply_vals.line_style = LineSolid;
  95.    ply_vals.cap_style  = CapRound;
  96.    ply_vals.join_style = JoinRound;
  97.    ply_vals.fill_style = FillSolid;
  98.    ply_vals.font       = font1;
  99.    ply_vals.graphics_exposures = 0;
  100.    ply_vals.clip_x_origin = 0;
  101.    ply_vals.clip_y_origin = 0;
  102.    ply_vals.clip_mask = None;
  103.    ply_mask = GCFunction | GCForeground | GCBackground |
  104.              GCLineWidth | GCLineStyle | GCCapStyle |
  105.              GCGraphicsExposures | GCClipXOrigin |
  106.              GCClipYOrigin | GCClipMask;
  107.    gc = XCreateGC(display,win,ply_mask,&ply_vals);
  108. }
  109.  
  110. static void
  111. initXRendering (Colormap cmap, Boolean double_b)
  112. {
  113.     makeGC(cmap);
  114.     if (double_b) {
  115.         XBuffer buffers[2];
  116.         sgiXnmbxCreateBuffers(dpy, XtWindow(glxarea), 2, 
  117.                               sgiNMBX_Frequent, sgiNMBX_Background, 
  118.                               0L, buffers);
  119.         sgiXnmbxSetDestinationOfGC(dpy, gc, sgiNMBX_Back);
  120.     }
  121. }
  122.  
  123. static void
  124. renderX (Widget w, Boolean double_b)
  125. {
  126.     XPoint pts[13];
  127.     Display * display = XtDisplay(w);
  128.     Window win = XtWindow(w);
  129.  
  130.     pts[0].x = 150; pts[0].y = 30;
  131.     pts[1].x = 30; pts[1].y = 270;
  132.     pts[2].x = 270; pts[2].y = 100;
  133.     pts[3].x = 30; pts[3].y = 100;
  134.     pts[4].x = 270; pts[4].y = 270;
  135.     pts[5].x = 150; pts[5].y = 30;
  136.  
  137.     XDrawLines(display,win,gc,pts,6,CoordModeOrigin);
  138.  
  139.     if (double_b) {
  140.         sgiXnmbxSwapWindow(display, win);
  141.     }
  142. }
  143.  
  144. void
  145. draw(Widget w, Boolean double_b)
  146. {
  147.     if (viewportUpdateNeeded)
  148.     updateViewport(w);
  149.  
  150.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  151.  
  152.     glBegin(GL_POLYGON);
  153.     glColor3f(0.0, 0.0, 0.0);
  154.     glVertex3f(-10.0, -10.0, 0.0);
  155.     glColor3f(0.7, 0.7, 0.7);
  156.     glVertex3f(10.0, -10.0, 0.0);
  157.     glColor3f(1.0, 1.0, 1.0);
  158.     glVertex3f(-10.0, 10.0, 0.0);
  159.     glEnd();
  160.     glBegin(GL_POLYGON);
  161.     glColor3f(1.0, 1.0, 0.0);
  162.     glVertex3f(0.0, -10.0, -10.0);
  163.     glColor3f(0.0, 1.0, 0.7);
  164.     glVertex3f(0.0, -10.0, 10.0);
  165.     glColor3f(0.0, 0.0, 1.0);
  166.     glVertex3f(0.0, 5.0, -10.0);
  167.     glEnd();
  168.     glBegin(GL_POLYGON);
  169.     glColor3f(1.0, 1.0, 0.0);
  170.     glVertex3f(-10.0, 6.0, 4.0);
  171.     glColor3f(1.0, 0.0, 1.0);
  172.     glVertex3f(-10.0, 3.0, 4.0);
  173.     glColor3f(0.0, 0.0, 1.0);
  174.     glVertex3f(4.0, -9.0, -10.0);
  175.     glColor3f(1.0, 0.0, 1.0);
  176.     glVertex3f(4.0, -6.0, -10.0);
  177.     glEnd();
  178.  
  179.     renderX(w, double_b);
  180.     glXSwapBuffers(XtDisplay(w), XtWindow(w));
  181.     XSync(XtDisplay(w), False);
  182. }
  183.  
  184. void
  185. expose(Widget w, XtPointer clientData, XtPointer callData)
  186. {
  187.     Boolean double_b = (Boolean)clientData;
  188.     draw(w, double_b);
  189. }
  190.  
  191. void
  192. resize(Widget w, XtPointer clientData, XtPointer callData)
  193. {
  194.     XmDrawingAreaCallbackStruct *cd = (XmDrawingAreaCallbackStruct *) callData;
  195.  
  196.     /* don't try OpenGL until window is realized! */
  197.     if (XtIsRealized(w)) {
  198.         updateViewport(w);
  199.     } else {
  200.         viewportUpdateNeeded = GL_TRUE;
  201.     }
  202. }
  203.  
  204. void
  205. input(Widget w, XtPointer clientData, XtPointer callData)
  206. {
  207.     Boolean double_b = (Boolean)clientData;
  208.     XmDrawingAreaCallbackStruct *cd = (XmDrawingAreaCallbackStruct *) callData;
  209.     char            buffer[1];
  210.     KeySym          keysym;
  211.     int             rc;
  212.  
  213.     switch (cd->event->type) {
  214.     case KeyRelease:
  215.     /*
  216.      * It is necessary to convert the keycode to a keysym before it is
  217.      * possible to check if it is an escape
  218.      */
  219.     rc = XLookupString((XKeyEvent *) cd->event, buffer, 1, &keysym, NULL);
  220.     switch (keysym) {
  221.     case XK_Up:
  222.         glRotatef(10.0, 0.0, 0.0, 1.0);
  223.         draw(w, double_b);
  224.         break;
  225.     case XK_Down:
  226.         glRotatef(-10.0, 0.0, 0.0, 1.0);
  227.         draw(w, double_b);
  228.         break;
  229.     case XK_Left:
  230.         glRotatef(-10.0, 0.0, 1.0, 0.0);
  231.         draw(w, double_b);
  232.         break;
  233.     case XK_Right:
  234.         glRotatef(10.0, 0.0, 1.0, 0.0);
  235.         draw(w, double_b);
  236.         break;
  237.     case XK_Escape:
  238.         exit(0);
  239.     }
  240.     break;
  241.     }
  242. }
  243.  
  244. static void
  245. initGraphics (GLXContext cx, Colormap cmap, Boolean double_b)
  246. {
  247.     unsigned int height = 0, width = 0;
  248.     /*
  249.      * Once widget is realized (ie, associated with a created X window), we
  250.      * can bind the OpenGL rendering context to the window.
  251.      */
  252.     glXMakeCurrent(dpy, XtWindow(glxarea), cx);
  253.  
  254.     /* setup OpenGL state */
  255.     glEnable(GL_DEPTH_TEST);
  256.     glDepthFunc(GL_LEQUAL);
  257.     glClearDepth(1.0);
  258.     glClearColor(0.0, 0.0, 0.0, 0.0);
  259.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  260.     glLoadIdentity();
  261.     gluPerspective(40.0, 1.0, 10.0, 200.0);
  262.     glTranslatef(0.0, 0.0, -50.0);
  263.     glRotatef(-58.0, 0.0, 1.0, 0.0);
  264.     initXRendering(cmap, double_b);
  265. }
  266.  
  267. static Boolean
  268. isValidXnmbxVisual(Display * dpy, XVisualInfo * vi)
  269. {
  270.     Boolean ret_value = False;
  271.     int error_base, event_base;
  272.     XVisualInfo * list = NULL;
  273.     int num_visuals = 0;
  274.     int num_v_caps = 0;
  275.     sgiXnmbxCapability * v_caps = NULL;
  276.  
  277.     XVisualInfo template;
  278.  
  279.     if (sgiXnmbxQueryExtension(dpy, &event_base, &error_base)) {
  280.  
  281.         v_caps = sgiXnmbxGetVisualCapabilities(dpy, vi->visual, &num_v_caps);;
  282.  
  283.         template.visualid = vi->visualid;
  284.         list = sgiXnmbxGetExtendedVisualInfo(dpy, VisualIDMask, 
  285.                                              &template, &num_visuals, 
  286.                                              num_v_caps, v_caps);
  287.         if (list != NULL) {
  288.             ret_value = True;
  289.         }
  290.         else {
  291.             fprintf(stderr, "No x double-buffering capability in visual\n");
  292.         }
  293.     }
  294.     else {
  295.         fprintf(stderr, "X multi-buffered extension not available\n");
  296.     }
  297.     return ret_value;
  298. }
  299.  
  300. static XVisualInfo *
  301. setupVisual (Display * display, Boolean * double_b)
  302. {
  303.     /* find an OpenGL-capable RGB visual with depth buffer */
  304.  
  305.     /* First try to find a double buffered visual. */
  306.     XVisualInfo * vi = glXChooseVisual(dpy, DefaultScreen(dpy), doubleBuf);
  307.  
  308.     /* Now make sure that we can use the Xnmbx extension with it. */
  309.     if ((vi == NULL) || (!isValidXnmbxVisual(dpy, vi))) {
  310.         vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
  311.         *double_b = False;
  312.     }
  313.     else {
  314.         *double_b = True;
  315.     }
  316.     return vi;
  317. }
  318.  
  319. main(int argc, char *argv[])
  320. {
  321.     Arg             args[20];
  322.     int             num;
  323.     XVisualInfo    *vi;
  324.     Colormap        cmap;
  325.     GLXContext      cx;
  326.     Boolean         double_b = False;
  327.  
  328.     /*
  329.      * XtVaAppInitialize is too automatic; we do step-by-step initialization
  330.      * of Xt so we can get Display* before the toplevel widget is created.
  331.      */
  332.     XtToolkitInitialize();
  333.     app = XtCreateApplicationContext();
  334.     XtAppSetFallbackResources(app, fallbackResources);
  335.     dpy = XtOpenDisplay(app, NULL, "glxmotif", "Glxmotif",
  336.         NULL, 0, &argc, argv);
  337.     if (dpy == NULL) {
  338.         XtAppError(app, "could not open display");
  339.     }
  340.  
  341.     vi = setupVisual(dpy, &double_b);
  342.     if (vi == NULL) {
  343.         XtAppError(app, "no RGB visual with depth buffer");
  344.     }
  345.     else if (double_b) {
  346.         fprintf(stderr, "Double buffering on\n");
  347.     }
  348.     else {
  349.         fprintf(stderr, "Single buffering on\n");
  350.     }
  351.  
  352.     /* create an OpenGL rendering context */
  353.     cx = glXCreateContext(dpy, vi, /* no sharing of display lists */ None,
  354.                /* direct rendering if possible */ GL_TRUE);
  355.     if (cx == NULL) {
  356.         XtAppError(app, "could not create rendering context");
  357.     }
  358.     /* create an X colormap since probably not using default visual */
  359.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  360.         vi->visual, AllocNone);
  361.  
  362.     num = 0;
  363.     XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy)); num++;
  364.     XtSetArg(args[num], XtNargc, argc); num++;
  365.     XtSetArg(args[num], XtNargv, argv); num++;
  366.     XtSetArg(args[num], XtNvisual, vi->visual); num++;
  367.     XtSetArg(args[num], XtNdepth, vi->depth); num++;
  368.     XtSetArg(args[num], XtNcolormap, cmap); num++;
  369.     toplevel = XtAppCreateShell(NULL, "Glxmotif", applicationShellWidgetClass,
  370.                 dpy, args, num);
  371.  
  372.     form = XmCreateForm(toplevel, "form", NULL, 0);
  373.     XtManageChild(form);
  374.  
  375.     num = 0;
  376.     XtSetArg(args[num], XtNx, 20); num++;
  377.     XtSetArg(args[num], XtNy, 20); num++;
  378.     XtSetArg(args[num], XmNbottomAttachment, XmATTACH_FORM); num++;
  379.     XtSetArg(args[num], XmNtopAttachment, XmATTACH_FORM); num++;
  380.     XtSetArg(args[num], XmNleftAttachment, XmATTACH_FORM); num++;
  381.     XtSetArg(args[num], XmNrightAttachment, XmATTACH_FORM); num++;
  382.     XtSetArg(args[num], XmNleftOffset, 20); num++;
  383.     XtSetArg(args[num], XmNtopOffset, 20); num++;
  384.     XtSetArg(args[num], XmNbottomOffset, 20); num++;
  385.     XtSetArg(args[num], XmNrightOffset, 20); num++;
  386.     frame = XmCreateFrame(form, "frame", args, num);
  387.     XtManageChild(frame);
  388.  
  389.     glxarea = XtCreateManagedWidget("glxarea", xmDrawingAreaWidgetClass, frame,
  390.                     NULL, 0);
  391.     XtAddCallback(glxarea, XmNexposeCallback, expose, (XtPointer)double_b);
  392.     XtAddCallback(glxarea, XmNresizeCallback, resize, NULL);
  393.     XtAddCallback(glxarea, XmNinputCallback, input, (XtPointer)double_b);
  394.  
  395.     XtRealizeWidget(toplevel);
  396.     initGraphics(cx, cmap, double_b);
  397.  
  398.     XtAppMainLoop(app);
  399. }
  400.